{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Isi Penting Generator: Karangan Style"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Generate a long text output with the style of an essay (karangan) when given important facts (isi penting in Malay)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div class=\"alert alert-info\">\n",
    "\n",
    "This tutorial is available as an IPython notebook at [Malaya/example/isi-penting-generator-karangan-style](https://github.com/huseinzol05/Malaya/tree/master/example/isi-penting-generator-karangan-style).\n",
    "    \n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div class=\"alert alert-warning\">\n",
    "\n",
    "The results you see here are generated using stochastic methods. Learn more about the stochastic process on <a href=\"https://en.wikipedia.org/wiki/Stochastic_process\" target=\"_blank\">Wikipedia</a>\n",
    "    \n",
    "</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 2.85 s, sys: 374 ms, total: 3.22 s\n",
      "Wall time: 2.86 s\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/maguswyvern/PythonVenvs/dev-malaya/lib/python3.10/site-packages/malaya/tokenizer.py:214: FutureWarning: Possible nested set at position 3397\n",
      "  self.tok = re.compile(r'({})'.format('|'.join(pipeline)))\n",
      "/home/maguswyvern/PythonVenvs/dev-malaya/lib/python3.10/site-packages/malaya/tokenizer.py:214: FutureWarning: Possible nested set at position 3927\n",
      "  self.tok = re.compile(r'({})'.format('|'.join(pipeline)))\n"
     ]
    }
   ],
   "source": [
    "%%time\n",
    "import malaya\n",
    "from pprint import pprint"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### List all available HuggingFace transformers"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `malaya` library has a built in function to find all available transformers for this task. As of writing we have two transformers which are:\n",
    "\n",
    "1. mesolitica/finetune-isi-penting-generator-t5-base-standard-bahasa-cased <br>\n",
    "https://huggingface.co/mesolitica/finetune-isi-penting-generator-t5-base-standard-bahasa-cased\n",
    "   \n",
    "2. mesolitica/finetune-isi-penting-generator-t5-small-standard-bahasa-cased <br>\n",
    "https://huggingface.co/mesolitica/finetune-isi-penting-generator-t5-small-standard-bahasa-cased"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'mesolitica/finetune-isi-penting-generator-t5-small-standard-bahasa-cased': {'Size (MB)': 242,\n",
       "  'ROUGE-1': 0.24620333,\n",
       "  'ROUGE-2': 0.05896076,\n",
       "  'ROUGE-L': 0.15158954,\n",
       "  'Suggested length': 1024},\n",
       " 'mesolitica/finetune-isi-penting-generator-t5-base-standard-bahasa-cased': {'Size (MB)': 892,\n",
       "  'ROUGE-1': 0.24620333,\n",
       "  'ROUGE-2': 0.05896076,\n",
       "  'ROUGE-L': 0.15158954,\n",
       "  'Suggested length': 1024}}"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "malaya.generator.isi_penting.available_huggingface"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Load HuggingFace\n",
    "\n",
    "The Generator transformer in `malaya` is quite unique, most of the text generative model we found on the internet like GPT2 or Markov simply just continue the prefix input from user, but not for our Generator transformer. \n",
    "\n",
    "We want to generate an article or karangan like high school when the users give 'isi penting' or important facts for the article."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```python\n",
    "def huggingface(\n",
    "    model: str = 'mesolitica/finetune-isi-penting-generator-t5-base-standard-bahasa-cased',\n",
    "    force_check: bool = True,\n",
    "    **kwargs,\n",
    "):\n",
    "    \"\"\"\n",
    "    Load HuggingFace model to generate text based on isi penting.\n",
    "\n",
    "    Parameters\n",
    "    ----------\n",
    "    model: str, optional (default='mesolitica/finetune-isi-penting-generator-t5-base-standard-bahasa-cased')\n",
    "        Check available models at `malaya.generator.isi_penting.available_huggingface`.\n",
    "    force_check: bool, optional (default=True)\n",
    "        Force check model one of malaya model.\n",
    "        Set to False if you have your own huggingface model.\n",
    "\n",
    "    Returns\n",
    "    -------\n",
    "    result: malaya.torch_model.huggingface.IsiPentingGenerator\n",
    "    \"\"\"\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "You are using the default legacy behaviour of the <class 'transformers.models.t5.tokenization_t5.T5Tokenizer'>. This is expected, and simply means that the `legacy` (previous) behavior will be used so nothing changes for you. If you want to use the new behaviour, set `legacy=False`. This should only be set if you understand what it means, and thoroughly read the reason why this was added as explained in https://github.com/huggingface/transformers/pull/24565\n"
     ]
    }
   ],
   "source": [
    "model = malaya.generator.isi_penting.huggingface()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here is the `generate` function and the parameters it expects. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```python\n",
    "def generate(\n",
    "    self,\n",
    "    strings: List[str],\n",
    "    mode: str = 'surat-khabar',\n",
    "    **kwargs,\n",
    "):\n",
    "    \"\"\"\n",
    "    generate a long text given a isi penting.\n",
    "\n",
    "    Parameters\n",
    "    ----------\n",
    "    strings : List[str]\n",
    "    mode: str, optional (default='surat-khabar')\n",
    "        Mode supported. Allowed values:\n",
    "\n",
    "        * ``'surat-khabar'`` - news style writing.\n",
    "        * ``'tajuk-surat-khabar'`` - headline news style writing.\n",
    "        * ``'artikel'`` - article style writing.\n",
    "        * ``'penerangan-produk'`` - product description style writing.\n",
    "        * ``'karangan'`` - karangan sekolah style writing.\n",
    "\n",
    "    **kwargs: vector arguments pass to huggingface `generate` method.\n",
    "        Read more at https://huggingface.co/docs/transformers/main_classes/text_generation\n",
    "\n",
    "    Returns\n",
    "    -------\n",
    "    result: List[str]\n",
    "    \"\"\"\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Benefits of HuggingFace\n",
    "\n",
    "With the `generate` method you can use Greedy, Beam, Sampling, Nucleus decoder and so much more, read more about it on the [HuggingFace Article on How to Generate](https://huggingface.co/blog/how-to-generate). And recently, HuggingFace also released a new article [Introducing Csearch](https://huggingface.co/blog/introducing-csearch)\n",
    "\n",
    "Let's give a few lines of important facts or isi penting for the model to use to generate text."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "isi_penting = ['ayam yang sihat dan sejahtera', \n",
    "               'nasi ayam yang sedap dan lazat', \n",
    "               'kedai bernama Husein Nasi Ayam']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['Nasi Ayam telah menjadi salah satu hidangan yang wajib ada di mana-mana '\n",
      " 'kawasan di Malaysia malah ada dikalangan masyarakat yang dihidangkan dengan '\n",
      " 'pelbagai jenis juadah seperti nasi kerabu dan mi goreng. Oleh itu, kita '\n",
      " 'perlu menelusuri setiap masalah yang membelenggu masyarakat kita kerana '\n",
      " 'terdapat segelintir masyarakat yang mengamalkan cara hidup yang tidak sihat. '\n",
      " 'Persoalan yang timbul ialah, apakah cara yang boleh dilakukan oleh ibu bapa '\n",
      " 'untuk menjaga anak mereka yang sedang hanyut dalam arus globalisasi kini? '\n",
      " 'Antara cara yang boleh dilakukan bagi membantu ibu bapa memelihara anak-anak '\n",
      " 'mereka dari segi pemakanan adalah dengan menyediakan makanan berkhasiat. Ibu '\n",
      " 'bapa hendaklah menyediakan makanan yang berkhasiat seperti nasi ayam, kuih '\n",
      " 'muih dan banyak lagi mengikut cara hidup rakyat Malaysia seperti peribahasa '\n",
      " 'Melayu, muafakat bagai aur dengan tebing. Dengan cara ini, ibu bapa dapat '\n",
      " 'mengetahui tabiat pemakanan anak-anak mereka dan mengelakkan mereka daripada '\n",
      " 'tabiat yang tidak sihat. Selain itu, ibu bapa juga digalakkan untuk '\n",
      " 'menyediakan makanan kepada anak-anak di sekolah. Perkara ini dapat membantu '\n",
      " 'mereka untuk mengawal berat badan dan meningkatkan tahap imunisasi badan. '\n",
      " 'Ibu bapa juga hendaklah menyediakan makanan kepada anak-anak dengan '\n",
      " 'sayur-sayuran dan buah-buahan yang cukup kerana mereka mengetahui bahawa '\n",
      " 'makanan ini mengandungi komponen yang']\n"
     ]
    }
   ],
   "source": [
    "pprint(model.generate(isi_penting, mode = 'karangan',\n",
    "    do_sample=True, \n",
    "    max_length=256, \n",
    "    top_k=50, \n",
    "    top_p=0.95,))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Previously we set the `top_k` parameter to `50`. A higher `top_k` value means the model considers more candidates, potentially leading to more diversity in the generated text but also increasing the computational cost.\n",
    "\n",
    "Now let's try lowering the parameter down and introduce the `penalty_alpha` argument to decrease randomness."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['Dalam era pasca-2020, negara telah mengalami pelbagai perubahan dasar dan '\n",
      " 'pembangunan yang rancak. Lantaran itu, pelbagai langkah perlu diambil untuk '\n",
      " 'menangani isu ini daripada terus menerus membelenggu masyarakat. Antara '\n",
      " 'tindakan yang boleh dilakukan adalah dengan menyediakan makanan kepada '\n",
      " 'anak-anak yang terabai dan ibu bapa yang kurang memberikan makanan kepada '\n",
      " 'anak-anak. Makanan ini hendaklah dimasak dalam jumlah yang cukup dan '\n",
      " 'hendaklah disediakan dalam periuk yang mengandungi ayam. Anak-anak boleh '\n",
      " 'bermain dengan anak ayam dan mereka akan memakannya dengan banyak seperti '\n",
      " 'cili padi. Oleh itu, ibu bapa hendaklah membantu anak-anak menyediakan '\n",
      " 'makanan kepada anak-anak dengan menyediakan makanan yang seimbang dan sihat. '\n",
      " 'Langkah lain yang boleh dilakukan adalah dengan menyediakan makanan ayam '\n",
      " 'kepada anak-anak. Pembekal makanan ringan ini hendaklah menyediakan makanan '\n",
      " 'yang berkhasiat dan seimbang kepada ayam yang telah digoreng. Makanan ini '\n",
      " 'mengandungi serat yang tinggi dan mengandungi serat yang tinggi untuk '\n",
      " 'memastikan telur-telur ayam sentiasa terhidang dan bebas daripada '\n",
      " 'penyakit-penyakit seperti darah tinggi, diabetes dan sebagainya. Anak-anak '\n",
      " 'juga perlulah diberi makanan yang mengandungi protein seperti daging, ayam '\n",
      " 'dan ikan. Ibu bapa juga boleh membawa anak-anak ke kedai makan yang menjual '\n",
      " 'pelbagai jenis produk makanan. Dengan cara ini, anak-anak akan mudah '\n",
      " 'tertarik']\n"
     ]
    }
   ],
   "source": [
    "pprint(model.generate(isi_penting, mode = 'karangan',\n",
    "    do_sample=True, \n",
    "    max_length=256, \n",
    "    penalty_alpha=0.8, top_k=4,))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Try changing the `isi_penting` variable and rerun the generate method again for more results. The sample isi penting here are borrowed from [mieadham86's Blogspot page](http://mieadham86.blogspot.com/2016/09/isi-isi-penting-karangan-bahasa-melayu.html)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "isi_penting = ['Rajin berusaha – tidak mudah putus asa',\n",
    "               'Menghormati orang yang lebih tua – mendapat keberkatan',\n",
    "               'Melibatkan diri secara aktif dalam bidang kokurikulum',\n",
    "               'Memberi tumpuan ketika guru mengajar.',\n",
    "               'Berdisiplin – menepati jadual yang disediakan.',\n",
    "               'Bercita-cita tinggi – mempunyai keazaman yang tinggi untuk berjaya']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['Sebagai anak yang bertanggungjawab, kita sewajarnya mempunyai nama keluarga '\n",
      " 'yang kukuh. Keluarga yang bertanggungjawab seharusnya mempunyai nama '\n",
      " 'keluarga yang mudah untuk digambarkan. Jika keluarga itu mempunyai nama '\n",
      " 'keluarga yang baik dan berunsurkan kasih sayang, pasti kita dapat '\n",
      " 'menghormati individu yang berjaya dalam hidup. Hal ini demikian kerana, kita '\n",
      " 'mampu menjadi seorang yang lebih baik daripada orang lain. Selain itu, '\n",
      " 'keluarga yang berjaya juga adalah penting dan harus dihargai. Kepelbagaian '\n",
      " 'latar belakang seperti agama dan bangsa telah memberikan kita pelbagai '\n",
      " 'manfaat dan keistimewaan yang wajar untuk kita nikmati. Namun begitu, tidak '\n",
      " 'dinafikan bahawa kepelbagaian kaum itu telah memberikan kesan kepada kita '\n",
      " 'sebagai anak didik. Ibarat peribahasa Melayu, melentur buluh biarlah dari '\n",
      " 'rebungnya. Sekiranya kita dapat berganding bahu untuk menjadikan keluarga '\n",
      " 'yang berjaya sebagai sebuah keluarga yang berbudi bahasa, kita boleh '\n",
      " 'menghayati segala minat dan manfaat yang akan diperoleh. Tamsilnya, Malaysia '\n",
      " 'juga telah berjaya mencapai pelbagai kejayaan seperti disentap oleh Datuk '\n",
      " 'Lee Chong Wei. Pencapaian ini merupakan hasil usaha gigih beliau yang tidak '\n",
      " 'mengenal erti putus asa atau lelah dalam mengejar cita-citanya untuk menjadi '\n",
      " 'seorang insan yang lebih baik daripada sebelumnya. Seperti peribahasa '\n",
      " 'Melayu, bersopan santun, melentur buluh biarlah dari rebung']\n"
     ]
    }
   ],
   "source": [
    "pprint(model.generate(isi_penting, do_sample=True, mode = 'karangan',\n",
    "    max_length=256,\n",
    "    top_k=50, \n",
    "    top_p=0.95, ))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['\"Bersatu kita teguh, bercerai kita roboh\". Itu antara peribahasa Melayu yang '\n",
      " 'sesuai untuk menggambarkan kepayahan golongan dewasa hari ini yang mempunyai '\n",
      " 'pelbagai jenis masalah. Akibat daripada itu, golongan dewasa ini telah '\n",
      " 'kehilangan sumber kewangan yang banyak untuk menampung kos hidup kerana '\n",
      " 'tidak mempunyai pekerjaan tetap dan terpaksa bekerja. Keadaan ini telah '\n",
      " 'memberi impak negatif kepada mereka yang mempunyai anak-anak. Mereka '\n",
      " 'kehilangan pekerjaan yang mampu memberi kesan yang besar kepada mereka dan '\n",
      " 'juga keluarga. Oleh itu, kita hendaklah mengkaji punca mereka menganggur. '\n",
      " 'Persoalannya ialah apakah punca-punca berlakunya masalah yang melibatkan '\n",
      " 'golongan dewasa ini? Antara punca yang signifikan dalam isu ini ialah mereka '\n",
      " 'tidak mempunyai masa dan wang yang cukup untuk diri sendiri. Hal ini '\n",
      " 'disebabkan oleh mereka terlalu sibuk bekerja sehingga tidak mempunyai masa '\n",
      " 'untuk diri sendiri. Sebagai contoh, bagi mereka yang bekerja di pasaraya, '\n",
      " 'waktu yang diambil adalah untuk membeli barang keperluan harian seperti nasi '\n",
      " 'lemak, mi goreng, kuih dan sebagainya. Oleh itu, mereka tidak mempunyai masa '\n",
      " 'dan wang yang cukup untuk diri sendiri. Selain daripada itu, faktor '\n",
      " 'kekurangan wang juga menjadi faktor golongan muda ini kurang mendapat '\n",
      " 'pekerjaan. Mereka kurang mendapat peluang untuk mendapat pekerjaan. Sebagai '\n",
      " 'contohnya, mereka hanya perlu membeli barang keperluan asas seperti beras, '\n",
      " 'gula dan tepung sahaja. Keadaan ini menyebabkan mereka tidak mendapat '\n",
      " 'pekerjaan yang sesuai']\n"
     ]
    }
   ],
   "source": [
    "pprint(model.generate(isi_penting, mode = 'karangan',\n",
    "    do_sample=True, \n",
    "    max_length=256, \n",
    "    penalty_alpha=0.8, top_k=4,))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.12"
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
